package org.jobtask.io;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.jobtask.config.ResourceMessages;
import org.jobtask.config.SystemIdentification;
import org.jobtask.schedule.JobTask;
import org.jobtask.schedule.KeyValue;
import org.jobtask.schedule.TaskGroup;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class JobIO {
	
	private static Document dom=null;
	private String currentPath="";
	
	public JobIO(){
		this("save/jobtask.xml");
	}
	
	public JobIO(String fileName){
		currentPath=fileName;
	}
	
	public void loadDom(){
		File file=new File(this.currentPath);
		DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder builder=factory.newDocumentBuilder();
			if(file.exists()){
				dom=builder.parse(this.currentPath);
			}else{
				dom=builder.newDocument();
				Element jobtaskElement=dom.createElement("jobtask");
				Element intervalElement=dom.createElement("interval");
				Element groupElement=dom.createElement("group");
				groupElement.setAttribute("id","default");
				groupElement.setAttribute("name",ResourceMessages.getString("TaskGroup.0"));
				jobtaskElement.appendChild(groupElement);
				dom.appendChild(jobtaskElement);
			}
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	public TaskGroup getTaskGroup(){
		TaskGroup group=new TaskGroup();
		NodeList groupNodes=this.getGroupElements();
		for(int index=0;index<groupNodes.getLength();index++){
			Node node=groupNodes.item(index);
			if(node.getNodeType()==Node.ELEMENT_NODE){
				Element groupElement=(Element)node;
				group.addGroup(new KeyValue(groupElement.getAttribute("id"), groupElement.getAttribute("name")), this.getJobsInGroup(groupElement));
			}
		}
		return group;
	}
	
	private NodeList getGroupElements(){
		Element rootElement=dom.getDocumentElement();
		NodeList groupNodes=rootElement.getElementsByTagName("group");
		return groupNodes;
	}
	
	public void addGroup(KeyValue group){
		Element newGroupElement=dom.createElement("group");
		newGroupElement.setAttribute("id",group.getKey().toString());
		newGroupElement.setAttribute("name",group.getValue().toString());
		 dom.getDocumentElement().appendChild(newGroupElement);
	}
	
	public Element getGroupElement(KeyValue group){
		NodeList groupList=this.getGroupElements();
		for(int index=0;index<groupList.getLength();index++){
			Element groupElement=(Element)groupList.item(index);
			if(groupElement.getAttribute("id").equals(group.getKey())){
				return groupElement;
			}
		}
		return null;
	}
	
	public void modifyGrouupNode(KeyValue group){
		Element newGrouup=this.getGroupElement(group);
		newGrouup.setAttribute("name",group.getValue().toString());
	}
	
	public ArrayList<JobTask> getJobsInGroup(Element groupNode){
		ArrayList<JobTask> jobList=new ArrayList<JobTask>();
		NodeList nodeList=groupNode.getElementsByTagName("job");
		for(int index=0;index<nodeList.getLength();index++){
			Node node=nodeList.item(index);
			if(node.getNodeType()==Node.ELEMENT_NODE){
				jobList.add(this.elementToJob((Element)node));
			}
		}
		return jobList;
	}
	
	
	
	public Element jobToElement(JobTask job){
		Element newJobElement=dom.createElement("job");
		newJobElement.setAttribute("id",job.getSequece()+"");
		newJobElement.setAttribute("name",job.getTaskName());
		newJobElement.setAttribute("type",job.getTaskType());
		newJobElement.setAttribute("file",job.getTaskFile());
		if(job.getSartTimes().size()>0){
			Element startTimeElement=dom.createElement("sarttimes");
			for(Iterator<Date> iter=job.getSartTimes().keySet().iterator();iter.hasNext();){
				Date key=iter.next();
				Element timeElement=dom.createElement("time");
				timeElement.setAttribute("state",job.getSartTimes().get(key));
				timeElement.setAttribute("timepoint",SystemIdentification.parseDateTimeToString(key,true));
				startTimeElement.appendChild(timeElement);
			}
			newJobElement.appendChild(startTimeElement);
		}
		if(job.getCount()!=null){
			Element countElement=dom.createElement("count");
			countElement.setTextContent(job.getCount()+"");
			newJobElement.appendChild(countElement);
		}
		if(job.getInterval()!=null){
			Element intervalElement=dom.createElement("interval");
			intervalElement.setTextContent(job.getInterval()+"");
			newJobElement.appendChild(intervalElement);
		}
		return newJobElement;
	}
	
	public JobTask elementToJob(Element element){
		JobTask job=new JobTask(Long.parseLong(element.getAttribute("id")));
		job.setTaskName(element.getAttribute("name"));
		job.setTaskFile(element.getAttribute("file"));
		job.setTaskType(element.getAttribute("type"));
		if(job.getTaskType().equals("SCHEDULING.REPEAT")){
			job.setCount(Integer.parseInt(((Element)element.getElementsByTagName("count").item(0)).getTextContent()));
			job.setInterval(Integer.parseInt(((Element)element.getElementsByTagName("interval").item(0)).getTextContent()));
		}else if(job.getTaskType().equals("SCHEDULING.TIMER")){
			NodeList timeList=((Element)element.getElementsByTagName("sarttimes").item(0)).getElementsByTagName("time");
			for(int index=0;index<timeList.getLength();index++){
				  Element timeElement=(Element)timeList.item(index);
				  job.addStartTime(SystemIdentification.parseStringToDateTime(timeElement.getAttribute("timepoint")), timeElement.getAttribute("state"));
			}
		}
		return job;
		
	}
	

	public void saveJob(){
		TransformerFactory tFactory = TransformerFactory.newInstance();
		Transformer transformer =null;
		DOMSource source=new DOMSource(dom);
		StreamResult result=new StreamResult(currentPath);
        try {
			transformer = tFactory.newTransformer();
			transformer.transform(source, result);
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}  
	}
	
	public void addJob(JobTask job,KeyValue group){
		Element groupElement=this.getGroupElement(group);
		groupElement.appendChild(this.jobToElement(job));
	}
	
	public void removeJob(JobTask job,KeyValue group){
		Element groupElement=this.getGroupElement(group);
		NodeList nodeList=groupElement.getElementsByTagName("job");
		for(int index=0;index<nodeList.getLength();index++){
			Element jobElement=(Element)nodeList.item(index);
			if(jobElement.getAttribute("id").equals(job.getSequece())){
				groupElement.removeChild(jobElement);
				break;
			}
		}
	}
	
	public void moveJobToGroup(JobTask job,KeyValue srcGroup,KeyValue targetGroup){
		Element groupElement=this.getGroupElement(srcGroup);
		Element targroupElement=this.getGroupElement(targetGroup);
		NodeList nodeList=groupElement.getElementsByTagName("job");
		for(int index=0;index<nodeList.getLength();index++){
			Element jobElement=(Element)nodeList.item(index);
			if(jobElement.getAttribute("id").equals(job.getSequece())){
				targroupElement.appendChild(jobElement);
				break;
			}
		}
	}
	
	public void removeGroup(KeyValue group){
		dom.getDocumentElement().removeChild(this.getGroupElement(group));
	}
	
	private Element getMonitorElement(){
		Element rootElement=dom.getDocumentElement();
		NodeList monitorNode=rootElement.getElementsByTagName("monitor");
		return (Element)monitorNode.item(0);
	}
	
	public long getInterval(){
		Element monitorElement=getMonitorElement();
		String value=monitorElement.getFirstChild().getTextContent();
		Long ms=new Long((value==null||value.equals(""))?"30":value);
		return ms;
	}
	
	public void setInterval(long ms){
		Element intervalElement=getMonitorElement();
		intervalElement.getFirstChild().setTextContent(ms+"");
	}
	
	public long getTimediff(){
		Element monitorElement=getMonitorElement();
		String value=monitorElement.getElementsByTagName("interval").item(0).getTextContent();
		Long ms=new Long((value==null||value.equals(""))?"30":value);
		return ms;
	}
	
	public void setTimediff(long ms){
		Element intervalElement=getMonitorElement();
		intervalElement.getFirstChild().setTextContent(ms+"");
	}
	
//	public void resetJobFile(){
//		File file=new File("");
//		StringBuilder content=new StringBuilder(512);
//		try {
//			String tempValue="";
//			BufferedReader read=new BufferedReader(new FileReader(file));
//			while(true){
//				tempValue=read.readLine();
//				if(tempValue==null) break;
//				content.append(tempValue+"\n");
//			}
//			read.close();
//			BufferedWriter writer=new BufferedWriter(new FileWriter(""));
//			writer.write(content.toString());
//			writer.close();
//		} catch (FileNotFoundException e) {
//			e.printStackTrace();
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//	}
}
